package com.winding.plugin.swagger.utils;

import com.google.common.collect.Maps;
import com.thoughtworks.qdox.model.*;
import io.swagger.models.Model;
import io.swagger.models.properties.Property;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.DigestUtils;

import java.io.File;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>TODO
 *
 * @author wind
 * @version 1.0
 * @since 2018/12/5
 */
@Slf4j
public class JavaSourceUtils {
    public final static String PARAM = "param";

    private JavaSourceUtils() {
    }

    /**
     * 列出项目下面的javafile
     *
     * @return the Object of {@code List<File>}
     */
    public static List<File> listProjectJavaFile() {
        File file = new File("");
        log.info("project java file path:{}", file.getAbsolutePath());
        file = file.getAbsoluteFile();
        List<File> allJavaFile = new ArrayList<>();
        File[] allFile = file.listFiles();
        Stack<File> stack = new Stack<>();
        if (allFile != null) {
            for (File tmp : allFile) {
                stack.push(tmp);
            }
        }
        while (!stack.isEmpty()) {
            File tmpFile = stack.pop();
            if (tmpFile.isDirectory()) {
                File[] files = tmpFile.listFiles();
                if (files != null) {
                    for (File tmp : files) {
                        stack.push(tmp);
                    }

                }
                continue;
            }
            if (StringUtils.endsWith(tmpFile.getName(), ".java")) {
                allJavaFile.add(tmpFile);
            }

        }
        return allJavaFile;
    }

    public static String getJavaClassDoc(JavaClass javaClass, String tag) {
        String doc = "";
        if (javaClass == null || CollectionUtils.isEmpty(javaClass.getTags())) {
            return doc;
        }
        for (DocletTag docletTag : javaClass.getTags()) {
            if (StringUtils.equals(docletTag.getName(), tag)) {
                for (String s : docletTag.getParameters()) {
                    doc += s;
                    break;
                }
            }
        }
        return doc;
    }

    public static Map<String, JavaMethod> getAllMethod(JavaClass javaClass) {
        if (javaClass == null) {
            return Maps.newHashMap();
        }
        return javaClass.getMethods().stream()
                .collect(Collectors.toMap(JavaMethod::getName, m -> m, (existingValue, newValue) -> existingValue));

    }

    public static Map<String, Method> getAllMethod(Class clazz) {
        return Stream.of(clazz.getMethods()).
                collect(Collectors.toMap(k->getUniqueName(k.getName(),k.getParameterTypes()), m -> m, (existingValue, newValue) -> existingValue));
    }

    public static String getUniqueName(String methodName, Class<?>[] classes ){
        StringBuilder builder=new StringBuilder(methodName);
        for (Class c:classes){
            builder.append(c.getSimpleName());
        }
        return DigestUtils.md5DigestAsHex(builder.toString().getBytes());
    }
    public static String getUniqueName(String methodName, List<JavaType> javaTypes){
        StringBuilder builder=new StringBuilder(methodName);
        for (JavaType javaType:javaTypes){
            builder.append(javaType.getValue());
        }
        return DigestUtils.md5DigestAsHex(builder.toString().getBytes());
    }
    /**
     * 读取字段描述到mode中
     *
     * @param model swagger模型类
     * @param javaClass swagger Java类
     */
    public static void readClassFieldDoc(Model model, JavaClass javaClass) {
        if (model == null) {
            return;
        }
        if (model.getProperties() == null) {
            return;
        }
        for (Map.Entry<String, Property> stringPropertyEntry : model.getProperties().entrySet()) {
            JavaField javaField = javaClass.getFieldByName(stringPropertyEntry.getKey());
            if (javaField == null) {
                continue;
            }
            List list=javaField.getTagsByName("required");
            boolean required=list!=null&&list.size()>0;
            stringPropertyEntry.getValue().setRequired(required);
            stringPropertyEntry.getValue().setDescription(javaField.getComment());
        }
    }

    public static String readParamDesc(Map<String, Map<String, String>> stringMapMap, String param) {
        Map<String, String> paramMap = stringMapMap.get(PARAM);
        String desc = "";
        if (paramMap != null && param != null) {
            desc = paramMap.getOrDefault(param, "");
        }
        return desc;
    }

    public static Map<String, Map<String, String>> readJavaMethodParam(JavaMethod javaMethod) {
        Map<String, Map<String, String>> mapMap = Maps.newHashMap();
        if (javaMethod != null) {
            if (CollectionUtils.isEmpty(javaMethod.getTags())) {
                return mapMap;
            }
            for (DocletTag docletTag : javaMethod.getTags()) {
                Map<String, String> data = mapMap.get(docletTag.getName());
                if (data == null) {
                    data = Maps.newHashMap();
                }
                mapMap.put(docletTag.getName(), data);
                String value = docletTag.getValue();
                //如果为空 那么就设置key和value都为空
                if (StringUtils.isEmpty(value)) {
                    data.put("", "");
                } else {
                    List<String> map = docletTag.getParameters();
                    String msg = "";
                    if (map.size() >= 2) {
                        msg += map.get(1);
                    } else if (map.size() == 1) {
                        msg += map.get(0);
                    }
                    data.put(map.get(0), msg);
                }
            }
        }
        return mapMap;
    }

}
